package stacks

import (
	"fmt"

	"cdk.tf/go/stack/interfaces"
	"cdk.tf/go/stack/models"
	"cdk.tf/go/stack/services"
	"cdk.tf/go/stack/utils"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
	"github.com/cdktf/cdktf-provider-aws-go/aws/v17/provider"
	"github.com/hashicorp/terraform-cdk-go/cdktf"
)

type MainStack struct {
	cdktf.TerraformStack
	Region           string
	VPCService       *services.VPCService
	SubnetService    *services.SubnetService
	SgService        *services.SecurityGroupService
	EC2Service       *services.EC2Service
	AWSClientManager *services.AWSClientManager
}

func NewMainStack(scope constructs.Construct, id string, region string) *MainStack {
	stack := cdktf.NewTerraformStack(scope, &id)

	// 配置 AWS Provider
	provider.NewAwsProvider(stack, jsii.String("AWS"), &provider.AwsProviderConfig{
		Region: jsii.String(region),
	})

	// 初始化服务
	awsClientManager := services.NewAWSClientManager()
	vpcService := services.NewVPCService()
	subnetService := services.NewSubnetService()
	sgService := services.NewSecurityGroupService()
	ec2Service := services.NewEC2Service(awsClientManager)

	mainStack := &MainStack{
		TerraformStack:   stack,
		Region:           region,
		VPCService:       vpcService,
		SubnetService:    subnetService,
		SgService:        sgService,
		EC2Service:       ec2Service,
		AWSClientManager: awsClientManager,
	}

	// 可选：创建示例基础设施
	mainStack.createExampleInfrastructure()

	return mainStack
}

// createExampleInfrastructure 创建示例网络基础设施
func (s *MainStack) createExampleInfrastructure() {
	// 创建 VPC
	vpcConfig := &interfaces.VPCConfig{
		Name:      "main-vpc",
		CidrBlock: "10.0.0.0/16",
		Region:    s.Region,
		Tags: map[string]string{
			"Environment": "development",
			"Project":     "cdktf-ec2",
		},
	}

	vpc, err := s.VPCService.CreateVPC(s, "MainVPC", vpcConfig)
	if err != nil {
		fmt.Printf("Error creating VPC: %v\n", err)
		return
	}

	// 创建子网
	subnetConfig := &interfaces.SubnetConfig{
		Name:                "public-subnet",
		CidrBlock:           "10.0.1.0/24",
		AvailabilityZone:    fmt.Sprintf("%sa", s.Region),
		VpcID:               *vpc.Id(),
		MapPublicIPOnLaunch: true,
		Tags: map[string]string{
			"Type":        "public",
			"Environment": "development",
		},
	}

	subnet, err := s.SubnetService.CreateSubnet(s, "PublicSubnet", subnetConfig)
	if err != nil {
		fmt.Printf("Error creating subnet: %v\n", err)
		return
	}

	// 创建安全组
	sgConfig := &interfaces.SecurityGroupConfig{
		Name:        "web-sg",
		Description: "Security group for web servers",
		VpcID:       *vpc.Id(),
		IngressRules: []interfaces.SecurityGroupRule{
			{
				Description: "SSH access",
				FromPort:    22,
				ToPort:      22,
				Protocol:    "tcp",
				CidrBlocks:  []string{"0.0.0.0/0"},
			},
			{
				Description: "HTTP access",
				FromPort:    80,
				ToPort:      80,
				Protocol:    "tcp",
				CidrBlocks:  []string{"0.0.0.0/0"},
			},
			{
				Description: "HTTPS access",
				FromPort:    443,
				ToPort:      443,
				Protocol:    "tcp",
				CidrBlocks:  []string{"0.0.0.0/0"},
			},
		},
		EgressRules: []interfaces.SecurityGroupRule{
			{
				Description: "All outbound traffic",
				FromPort:    0,
				ToPort:      0,
				Protocol:    "-1",
				CidrBlocks:  []string{"0.0.0.0/0"},
			},
		},
		Tags: map[string]string{
			"Environment": "development",
			"Purpose":     "web-server",
		},
	}

	sg, err := s.SgService.CreateSecurityGroup(s, "WebSecurityGroup", sgConfig)
	if err != nil {
		fmt.Printf("Error creating security group: %v\n", err)
		return
	}

	// 添加 Terraform 输出
	cdktf.NewTerraformOutput(s, jsii.String("vpc_id"), &cdktf.TerraformOutputConfig{
		Value:       vpc.Id(),
		Description: jsii.String("ID of the main VPC"),
	})

	cdktf.NewTerraformOutput(s, jsii.String("subnet_id"), &cdktf.TerraformOutputConfig{
		Value:       subnet.Id(),
		Description: jsii.String("ID of the public subnet"),
	})

	cdktf.NewTerraformOutput(s, jsii.String("security_group_id"), &cdktf.TerraformOutputConfig{
		Value:       sg.Id(),
		Description: jsii.String("ID of the web security group"),
	})

	fmt.Printf("Created infrastructure:\n")
	fmt.Printf("  VPC ID: %s\n", *vpc.Id())
	fmt.Printf("  Subnet ID: %s\n", *subnet.Id())
	fmt.Printf("  Security Group ID: %s\n", *sg.Id())
}

// CreateEC2InstanceWithConfig 使用配置创建EC2实例
func (s *MainStack) CreateEC2InstanceWithConfig(config *interfaces.EC2Config) (*models.EC2OperationResponse, error) {
	instance, err := s.EC2Service.CreateEC2Instance(s, config.Name, config)
	if err != nil {
		return &models.EC2OperationResponse{
			Success: false,
			Message: fmt.Sprintf("Failed to create EC2 instance: %v", err),
		}, err
	}

	// 添加实例输出
	cdktf.NewTerraformOutput(s, jsii.String(fmt.Sprintf("%s_instance_id", config.Name)), &cdktf.TerraformOutputConfig{
		Value:       instance.Id(),
		Description: jsii.String(fmt.Sprintf("ID of the %s instance", config.Name)),
	})

	return &models.EC2OperationResponse{
		Success:    true,
		Message:    "EC2 instance creation initiated",
		InstanceID: *instance.Id(),
	}, nil
}

// CreateWebServer 创建Web服务器实例
func (s *MainStack) CreateWebServer() (*models.EC2OperationResponse, error) {
	// 获取基础设施ID（这里需要先创建基础设施）
	vpcs := s.VPCService.ListVPCs()
	subnets := s.SubnetService.ListSubnets()
	sgs := s.SgService.ListSecurityGroups()

	if len(vpcs) == 0 || len(subnets) == 0 || len(sgs) == 0 {
		return &models.EC2OperationResponse{
			Success: false,
			Message: "Please create infrastructure first",
		}, fmt.Errorf("infrastructure not found")
	}

	// 使用第一个找到的资源（在实际应用中应该更精确地选择）
	var vpcID, subnetID, sgID string
	for id := range vpcs {
		vpcID = id
		break
	}
	for id := range subnets {
		subnetID = id
		break
	}
	for id := range sgs {
		sgID = id
		break
	}

	config := &interfaces.EC2Config{
		Name:             "web-server",
		AmiID:            getAMIForRegion(s.Region),
		InstanceType:     "t2.micro",
		KeyName:          "my-key-pair", // 需要提前创建密钥对
		SubnetID:         subnetID,
		SecurityGroupIDs: utils.ConvertStringSliceToPointer([]string{sgID}),
		UserData: `#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from CDKTF Web Server!</h1>" > /var/www/html/index.html
`,
		Tags: map[string]string{
			"Environment": "production",
			"Role":        "web-server",
			"Project":     "cdktf-demo",
		},
		AssociatePublicIP: true,
	}

	return s.CreateEC2InstanceWithConfig(config)
}

// CreateDatabaseServer 创建数据库服务器实例
func (s *MainStack) CreateDatabaseServer() (*models.EC2OperationResponse, error) {
	vpcs := s.VPCService.ListVPCs()
	subnets := s.SubnetService.ListSubnets()
	sgs := s.SgService.ListSecurityGroups()

	if len(vpcs) == 0 || len(subnets) == 0 || len(sgs) == 0 {
		return &models.EC2OperationResponse{
			Success: false,
			Message: "Please create infrastructure first",
		}, fmt.Errorf("infrastructure not found")
	}

	var vpcID, subnetID, sgID string
	for id := range vpcs {
		vpcID = id
		break
	}
	for id := range subnets {
		subnetID = id
		break
	}
	for id := range sgs {
		sgID = id
		break
	}

	config := &interfaces.EC2Config{
		Name:             "db-server",
		AmiID:            getAMIForRegion(s.Region),
		InstanceType:     "t2.medium",
		KeyName:          "my-key-pair",
		SubnetID:         subnetID,
		SecurityGroupIDs: utils.ConvertStringSliceToPointer([]string{sgID}),
		UserData: `#!/bin/bash
yum update -y
yum install -y mysql-server
`,
		Tags: map[string]string{
			"Environment": "production",
			"Role":        "database",
			"Project":     "cdktf-demo",
		},
		AssociatePublicIP: false, // 数据库服务器通常不需要公网IP
	}

	return s.CreateEC2InstanceWithConfig(config)
}

// GetStackOutputs 获取堆栈输出
func (s *MainStack) GetStackOutputs() map[string]string {
	outputs := make(map[string]string)

	// 这里可以添加获取特定输出的逻辑
	// 在实际应用中，可以通过 CDKTF 的输出机制获取

	return outputs
}

// DestroyStack 销毁堆栈资源
func (s *MainStack) DestroyStack() (*models.EC2OperationResponse, error) {
	// 这里可以实现资源清理逻辑
	// 注意：CDKTF 主要通过 `cdktf destroy` 命令来销毁资源

	return &models.EC2OperationResponse{
		Success: true,
		Message: "Stack destruction should be performed using 'cdktf destroy' command",
	}, nil
}

// getAMIForRegion 根据区域获取合适的AMI
func getAMIForRegion(region string) string {
	// Amazon Linux 2 AMI (HVM), SSD Volume Type
	amiMap := map[string]string{
		"us-east-1":      "ami-0c55b159cbfafe1f0", // N. Virginia
		"us-west-2":      "ami-0c2d06ec50cc46ea6", // Oregon
		"eu-west-1":      "ami-0d1c5abf5a6c83eb2", // Ireland
		"ap-northeast-1": "ami-0f310e6e7f6c53c5d", // Tokyo
		"ap-southeast-1": "ami-0b1e534a4b4f353c3", // Singapore
	}

	if ami, exists := amiMap[region]; exists {
		return ami
	}

	// 默认返回 us-west-2 的AMI
	return "ami-0c2d06ec50cc46ea6"
}
